'use strict';
var _ = require('lodash');
var Injector = require('injector');
var mongodb = require('mongodb');
var Q = require('q');

module.exports = Injector.define([
    'config/mongodb'
], createModule);

function createModule(mongodbConfig) {

    var mongodbHelper = {};

    mongodbHelper.mongodb = mongodb;

    mongodbHelper.resultN = function (result) {
        return result.result.n;
    };

    mongodbHelper.resultInsertedId = function (result) {
        if (result.result.n) {
            return String(result.insertedId);
        }
    };

    mongodbHelper.mapDocId = function (newIdName) {
        return function (doc) {
            if (doc) {
                doc[newIdName] = String(doc._id);
                return _.omit(doc, '_id');
            } else {
                return doc;
            }
        };
    };

    mongodbHelper.mapDocsId = function (newIdName) {
        return function (docs) {
            return _.map(docs, mongodbHelper.mapDocId(newIdName));
        };
    };

    mongodbHelper.fillDefToDoc = function (defaultDocument) {
        return function (doc) {
            return _.defaults(doc, defaultDocument);
        };
    };

    mongodbHelper.fillDefToDocs = function (defaultDocument) {
        return function (docs) {
            return _.map(docs, mongodbHelper.fillDefToDoc(defaultDocument));
        };
    };

    mongodbHelper.pickOneDoc = function () {
        return function (docs) {
            if (docs.length) {
                return docs[0];
            }
        };
    };

    mongodbHelper.fillIdToDoc = function () {
        return function (doc) {
            return _.extend(doc, {
                _id: mongodb.ObjectId()
            });
        };
    };

    mongodbHelper.fillIdToDocs = function () {
        return function (docs) {
            return _.map(docs, mongodbHelper.fillIdToDoc());
        };
    };

    mongodbHelper.makeFilterWithObjectId = function (id, other) {
        return _.extend({
            _id: mongodb.ObjectId(id)
        }, other);
    };

    mongodbHelper.makeFilterWithObjectIds = function (ids, other) {
        return _.extend({
            _id: {
                $in: _.map(ids, function (id) {
                    return mongodb.ObjectId(id);
                })
            }
        }, other);
    };

    mongodbHelper.makeFilterWithoutObjectIds = function (ids, other) {
        return _.extend({
            _id: {
                $nin: _.map(ids, function (id) {
                    return mongodb.ObjectId(id);
                })
            }
        }, other);
    };

    mongodbHelper.newObjectIdString = function () {
        return String(mongodb.ObjectId());
    };

    var exports = {};
    _.each(mongodbHelper, function (func, name) {
        Object.defineProperty(exports, name, {
            get: function () {
                return func;
            }
        });
    });

    _.each(mongodbConfig, function (config, instanceName) {
        exports[instanceName] = Q.ninvoke(mongodb.MongoClient, 'connect', config.url, config.options);
    });

    return exports;
}
